home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / cagd_lib / cagd_arc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  4.2 KB  |  128 lines

  1. /******************************************************************************
  2. * Cagd_Arc.c - Curve representation of arcs and circles                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Jun. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "cagd_loc.h"
  11.  
  12. #define UNIT_CIRCLE_ORDER 3
  13. #define UNIT_CIRCLE_LENGTH 9      /* Nine control points in the unit circle. */
  14.  
  15. static int UnitCircleKnots[UNIT_CIRCLE_ORDER + UNIT_CIRCLE_LENGTH] =
  16.                     { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 };
  17. static int UnitCircleX[UNIT_CIRCLE_LENGTH] = { 1, 1, 0, -1, -1, -1, 0, 1, 1 };
  18. static int UnitCircleY[UNIT_CIRCLE_LENGTH] = { 0, 1, 1, 1, 0, -1, -1, -1, 0 };
  19.  
  20. /******************************************************************************
  21. * Creates an arc at the specified position as a rational Bezier curve.          *
  22. *   The arc is assumed to be less than 180 degrees from Start to End in the   *
  23. * shorter path as arc where Center as arc center.                  *
  24. ******************************************************************************/
  25. CagdCrvStruct *BzrCrvCreateArc(CagdPtStruct *Start, CagdPtStruct *Center,
  26.                                  CagdPtStruct *End)
  27. {
  28.     int i;
  29.     CagdCrvStruct
  30.     *Arc = BzrCrvNew(3, CAGD_PT_P3_TYPE);
  31.     CagdRType Len, CosAlpha, Radius,
  32.     **Points = Arc -> Points;
  33.     CagdVecStruct V1, V2, V;
  34.  
  35.     /* Copy first point. */
  36.     Points[X][0] = Start -> Pt[0];
  37.     Points[Y][0] = Start -> Pt[1];
  38.     Points[Z][0] = Start -> Pt[2];
  39.     Points[W][0] = 1.0;
  40.  
  41.     /* Copy last point. */
  42.     Points[X][2] = End -> Pt[0];
  43.     Points[Y][2] = End -> Pt[1];
  44.     Points[Z][2] = End -> Pt[2];
  45.     Points[W][2] = 1.0;
  46.  
  47.     /* Compute position of middle point. */
  48.     Len = 0.0;
  49.     for (i = 0; i < 3; i++) {
  50.     V1.Vec[i] = Start -> Pt[i] - Center -> Pt[i];
  51.     V2.Vec[i] = End -> Pt[i] - Center -> Pt[i];
  52.     V.Vec[i] = V1.Vec[i] + V2.Vec[i];
  53.     Len += SQR(V.Vec[i]);
  54.     }
  55.  
  56.     if (APX_EQ(Len, 0.0)) {
  57.     CagdCrvFree(Arc);
  58.     FATAL_ERROR(CAGD_ERR_180_ARC);
  59.     return NULL;
  60.     }
  61.     else
  62.     Len = sqrt(Len);
  63.  
  64.     for (i = 0; i < 3; i++)
  65.     V.Vec[i] /= Len;
  66.  
  67.     /* Compute cosine alpha (where alpha is the angle between V and V1. */
  68.     Radius = sqrt(DOT_PROD(V1.Vec, V1.Vec));
  69.     CosAlpha = DOT_PROD(V1.Vec, V.Vec) / Radius;
  70.  
  71.     CAGD_DIV_VECTOR(V, CosAlpha);
  72.     CAGD_MULT_VECTOR(V, Radius);
  73.  
  74.     /* And finally fill in the middle point with CosAlpha as the Weight. */
  75.     Points[X][1] = (Center -> Pt[0] + V.Vec[0]) * CosAlpha;
  76.     Points[Y][1] = (Center -> Pt[1] + V.Vec[1]) * CosAlpha;
  77.     Points[Z][1] = (Center -> Pt[2] + V.Vec[2]) * CosAlpha;
  78.     Points[W][1] = CosAlpha;
  79.  
  80.     return Arc;
  81. }
  82.  
  83. /******************************************************************************
  84. * Creates a circle at the specified position as a rational Bspline curve.     *
  85. *   Construct a circle as 4 90 degrees arcs of rationa bezier segments using  *
  86. * the constants defined above.                              *
  87. ******************************************************************************/
  88. CagdCrvStruct *BspCrvCreateUnitCircle(void)
  89. {
  90.     int i;
  91.     CagdRType Weight,
  92.         W45 = sin(M_PI / 4.0);
  93.     CagdCrvStruct
  94.     *Circle = BspCrvNew(UNIT_CIRCLE_LENGTH, UNIT_CIRCLE_ORDER,
  95.                                   CAGD_PT_P3_TYPE);
  96.     CagdRType
  97.     **Points = Circle -> Points;
  98.  
  99.     for (i = 0; i < UNIT_CIRCLE_LENGTH + UNIT_CIRCLE_ORDER; i++)
  100.     Circle -> KnotVector[i] = UnitCircleKnots[i];
  101.  
  102.     for (i = 0; i < UNIT_CIRCLE_LENGTH; i++) {
  103.     Weight = Points[W][i] = i % 2 ? W45: 1.0;
  104.     Points[X][i] = UnitCircleX[i] * Weight;
  105.     Points[Y][i] = UnitCircleY[i] * Weight;
  106.     Points[Z][i] = 0.0;
  107.     }
  108.  
  109.     return Circle;
  110. }
  111.  
  112.  
  113. /******************************************************************************
  114. * Creates a circle at the specified position as a rational bezier curve.      *
  115. ******************************************************************************/
  116. CagdCrvStruct *BspCrvCreateCircle(CagdPtStruct *Center, CagdRType Radius)
  117. {
  118.     CagdPtStruct OriginPt;
  119.     CagdCrvStruct *Circle = BspCrvCreateUnitCircle();
  120.  
  121.     /* Do it in two stages: 1. scale, 2. translate */
  122.     OriginPt.Pt[0] = OriginPt.Pt[1] = OriginPt.Pt[2] = 0.0;
  123.     CagdCrvTransform(Circle, OriginPt.Pt, Radius);
  124.     CagdCrvTransform(Circle, Center -> Pt, 1.0);
  125.  
  126.     return Circle;
  127. }
  128.